package cn.iocoder.yudao.module.apijson.framework.service;

import apijson.*;
import cn.iocoder.yudao.module.apijson.framework.APIJSONApplication;
import cn.iocoder.yudao.module.apijson.framework.APIJSONParser;
import cn.iocoder.yudao.module.apijson.framework.APIJSONVerifier;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.rmi.ServerException;
import java.util.Map;

import static apijson.RequestMethod.*;
import static cn.iocoder.yudao.module.apijson.framework.APIJSONConstant.*;
import static cn.iocoder.yudao.module.apijson.framework.APIJSONConstant.REQUEST_;

@Slf4j
@Service
public class ApiJsonServiceImpl implements ApiJsonService {
    public static APIJSONParser COMMON_PARSER = APIJSONApplication.createParser();

    public static JSONObject newErrorResult(Exception e) {
        return newErrorResult(e, false);
    }

    public static JSONObject newErrorResult(Exception e, boolean isRoot) {
        return COMMON_PARSER.newErrorResult(e, isRoot);
    }

    /**
     * 新建带状态内容的JSONObject
     */
    public static JSONObject newResult(int code, String msg, String warn, boolean isRoot) {
        return extendResult(null, code, msg, warn, isRoot);
    }

    /**
     * 添加JSONObject的状态内容，一般用于错误提示结果
     */
    public static JSONObject extendResult(JSONObject object, int code, String msg, String warn, boolean isRoot) {
        return COMMON_PARSER.extendResult(JSON.createJSONObject(object), code, msg, warn, isRoot);
    }

    /**
     * 获取请求成功的状态内容
     */
    public static JSONObject newSuccessResult() {
        return newSuccessResult(null);
    }

    /**
     * 获取请求成功的状态内容
     */
    public static JSONObject newSuccessResult(String warn) {
        return newSuccessResult(warn, false);
    }

    /**
     * 获取请求成功的状态内容
     */
    public static JSONObject newSuccessResult(String warn, boolean isRoot) {
        return newResult(JSONResponse.CODE_SUCCESS, JSONResponse.MSG_SUCCEED, warn, isRoot);
    }


    /**
     * 重新加载配置
     * {
     * "type": "ALL",  //重载对象，ALL, FUNCTION, REQUEST, ACCESS，非必须
     * "phone": "13000082001",
     * "verify": "1234567" //验证码，对应类型为 Verify.TYPE_RELOAD
     * }
     * </pre>
     */
    @Override
    public JSONObject reload(String type) {
        JSONObject result = newSuccessResult();
        boolean reloadAll = StringUtil.isEmpty(type, true) || "ALL".equals(type);

        if (reloadAll || "ACCESS".equals(type)) {
            try {
                if (!reloadAll && !APIJSONVerifier.ENABLE_VERIFY_ROLE) {
                    throw new UnsupportedOperationException("AbstractVerifier.ENABLE_VERIFY_ROLE == false 时不支持校验角色权限！" +
                            "如需支持则设置 AbstractVerifier.ENABLE_VERIFY_ROLE = true ！");
                }

                if (APIJSONVerifier.ENABLE_VERIFY_ROLE) {
                    result.put(ACCESS_, APIJSONVerifier.initAccess(false));
                }
            } catch (ServerException e) {
                log.error(e.getMessage(), e);
                result.put(ACCESS_, newErrorResult(e));
            }
        }

        if (reloadAll || "FUNCTION".equals(type)) {
            try {
                if (!reloadAll && !APIJSONFunctionParserBase.ENABLE_REMOTE_FUNCTION) {
                    throw new UnsupportedOperationException("AbstractFunctionParser.ENABLE_REMOTE_FUNCTION" +
                            " == false 时不支持远程函数！如需支持则设置 AbstractFunctionParser.ENABLE_REMOTE_FUNCTION = true ！");
                }

                if (APIJSONFunctionParserBase.ENABLE_REMOTE_FUNCTION) {
                    result.put(FUNCTION_, APIJSONFunctionParserBase.init());
                }
            } catch (ServerException e) {
                log.error(e.getMessage(), e);
                result.put(FUNCTION_, newErrorResult(e));
            }
        }

        if (reloadAll || "REQUEST".equals(type)) {
            try {
                if (!reloadAll && !APIJSONVerifier.ENABLE_VERIFY_CONTENT) {
                    throw new UnsupportedOperationException("AbstractVerifier.ENABLE_VERIFY_CONTENT == false 时不支持校验请求传参内容！" +
                            "如需支持则设置 AbstractVerifier.ENABLE_VERIFY_CONTENT = true ！");
                }

                if (APIJSONVerifier.ENABLE_VERIFY_CONTENT) {
                    result.put(REQUEST_, APIJSONVerifier.initRequest(false));
                }
            } catch (ServerException e) {
                log.error(e.getMessage(), e);
                result.put(REQUEST_, newErrorResult(e));
            }
        }

        return result;
    }


    /**
     * 获取
     */
    @Override
    public String get(String request) {
        return parse(GET, request);
    }

    @Override
    public String getByTag(String tag, String request) {
        return parseByTag(GET, tag, null, request);
    }

    /**
     * 计数
     *
     * @param request 只用String，避免encode后未decode
     */
    @Override
    public String head(String request) {
        return parse(HEAD, request);
    }

    /**
     * 限制性HEAD，request和response都非明文，浏览器看不到，用于对安全性要求高的HEAD请求
     *
     * @param request 只用String，避免encode后未decode
     */
    public String heads(String request) {
        return parse(HEADS, request);
    }

    /**
     * 限制性GET，request和response都非明文，浏览器看不到，用于对安全性要求高的GET请求
     *
     * @param request 只用String，避免encode后未decode
     */
    public String gets(String request) {
        return parse(GETS, request);
    }

    /**
     * 新增
     *
     * @param request 只用String，避免encode后未decode
     */
    public String post(String request) {
        return parse(POST, request);
    }

    /**
     * 修改
     *
     * @param request 只用String，避免encode后未decode
     */
    public String put(String request) {
        return parse(PUT, request);
    }

    @Override
    public String putByTag(String tag, String request) {
        return parseByTag(PUT, tag, null, request);
    }

    /**
     * 删除
     *
     * @param request 只用String，避免encode后未decode
     */
    public String delete(String request) {
        return parse(DELETE, request);
    }

    @Override
    public String deleteByTag(String tag, String request) {
        return parseByTag(DELETE, tag, null, request);
    }

    /**
     * 支持全局事物、批量执行多条语句
     *
     * @param request 只用String，避免encode后未decode
     */
    public String crud(String request) {
        return parse(CRUD, request);
    }

    private String parse(RequestMethod method, String request) {
        if (APIJSONVerifier.ENABLE_APIJSON_ROUTER && !Log.DEBUG) {
            return JSON.toJSONString(
                    newErrorResult(
                            new IllegalArgumentException("APIJSONVerifier.ENABLE_APIJSON_ROUTER = true 已启用 router，" +
                                    "Log.DEBUG = false 时不允许调用 /router/{method}/{tag} 外的万能通用接口！"
                            )
                    )
            );
        }
        return newParser(method).parse(request);
    }

    private APIJSONParser newParser(RequestMethod method) {
        APIJSONParser parser = APIJSONApplication.createParser();
        parser.setMethod(method);
        parser.setRequestURL(getRequestURL());
        return parser;
    }

    private String getRequestURL() {
        return null;
    }

    @Override
    public String postByTag(String tag, String request) {
        return parseByTag(POST, tag, null, request);
    }

    public String parseByTag(RequestMethod method, String tag, Map<String, String> params, String request) {
        if (APIJSONVerifier.ENABLE_APIJSON_ROUTER && !Log.DEBUG) {
            return JSON.toJSONString(
                    newErrorResult(
                            new IllegalArgumentException("APIJSONVerifier.ENABLE_APIJSON_ROUTER = true 已启用 router，" +
                                    "Log.DEBUG = false 时不允许调用 /router/{method}/{tag} 外的万能通用接口！"
                            )
                    )
            );
        }

        APIJSONParser parser = newParser(method);
        JSONObject req = parser.wrapRequest(method, tag, JSON.parseObject(request), false);
        if (req == null) {
            req = JSON.createJSONObject();
        }
        if (params != null && !params.isEmpty()) {
            req.putAll(params);
        }
        return parser.parse(req);
    }

}
